#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include<string>
#include<vector>
#include<iostream>
#include<thread>
#include<mutex>
#include"Thread.hpp"
#include"LockGuard.hpp"

using namespace ThreadModule;


class ThreadData
{
public:
    ThreadData(int &tickets, const std::string &name, std::mutex &mutex)
        : _tickets(tickets), _name(name), _total(0), _mutex(mutex)
    {
    }
    ~ThreadData()
    {
    }

public:
    int &_tickets; // 所有的线程，最后都会引用同一个全局的g_tickets
    std::string _name;
    int _total;
    std::mutex &_mutex;
};

int g_tickets = 10000;// 共享资源，没有保护的, 临界资源

void *route(ThreadData *td)
{
    while ( 1 ) 
    {
        //LockGuard guard(&td->_mutex);// 临时对象, RAII风格的加锁和解锁

        td->_mutex.lock();
        if (td->_tickets > 0 ) 
        {
            usleep(1000);
            printf("%s running, get tickets: %d\n", td->_name.c_str(), td->_tickets); 
            td->_tickets--;
            td->_mutex.unlock();

            td->_total++;
        } 

        else 
        {
            td->_mutex.unlock();
            break;
        }
    }

    return NULL;
}

const int num = 4;
int main()
{
    // pthread_mutex_t mutex;
    // pthread_mutex_init(&mutex, nullptr);

    std::mutex mutex;

    std::vector<Thread<ThreadData *>> threads;
    std::vector<ThreadData *> datas;
    // 1. 创建一批线程
    for (int i = 0; i < num; i++)
    {
        std::string name = "thread-" + std::to_string(i + 1);
        ThreadData *td = new ThreadData(g_tickets, name, mutex);
        threads.emplace_back(route, td, name);
        datas.emplace_back(td);
    }

    // 2. 启动 一批线程
    for (auto &thread : threads)
    {
        thread.Start();
    }

    // 3. 等待一批线程
    for (auto &thread : threads)
    {
        thread.Join();
        std::cout << "wait thread done, thread is: " << thread.name() << std::endl;
    }


     // 4. 输出统计数据
    for (auto data : datas)
    {
        std::cout << data->_name << " : " << data->_total << std::endl;
        delete data;
    }

    //pthread_mutex_destroy(&mutex);
    return 0;
}



